<template>
  <div>
    <t-card class="list-card-container" :bordered="false">
      <t-row justify="space-between">
        <t-input v-model="searchValue" class="search-input" placeholder="请输入关键词信息" clearable>
          <template #suffix-icon>
            <search-icon size="20px" />
          </template>
        </t-input>
        <div class="left-operation-container">
          <t-button @click="formVisible = true"> 新建爬虫 </t-button>
          <t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出 </t-button>
        </div>
      </t-row>

      <div class="table-container">
        <t-table
          :columns="columns"
          :data="data"
          :rowKey="rowKey"
          :verticalAlign="verticalAlign"
          :hover="hover"
          :pagination="pagination"
          :selected-row-keys="selectedRowKeys"
          :loading="dataLoading"
          @page-change="rehandlePageChange"
          @change="rehandleChange"
          @select-change="rehandleSelectChange"
          :headerAffixedTop="true"
          :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }"
        >
          <template #status="{ row }">
            <t-tag v-if="row.status === CRAWLER_STATUS.FAIL" theme="danger" variant="light">失败</t-tag>
            <t-tag v-if="row.status === CRAWLER_STATUS.RUNNING" theme="primary" variant="light">进行中</t-tag>
            <t-tag v-if="row.status === CRAWLER_STATUS.FINISH" theme="success" variant="light">已完成</t-tag>
          </template>
          <template #op="slotProps">
            <t-button
              size="small"
              shape="round"
              theme="default"
              :disabled="isRunning(slotProps.row)"
              @click="startCrawler(slotProps.row)"
              :class="{ 'running-button': isRunning(slotProps.row) }"
            >
              {{ isRunning(slotProps.row) ? '运行中' : '运行' }}
            </t-button>
            <t-button size="small" shape="round" theme="default" @click="handleClickDetail(slotProps.row)">
              详情
            </t-button>
            <t-button size="small" shape="round" theme="danger" @click="handleClickDelete(slotProps)"> 删除 </t-button>
          </template>
        </t-table>
      </div>
    </t-card>
    <!-- 删除操作弹窗 -->
    <t-dialog
      header="确认删除当前所选爬虫？"
      :body="confirmBody"
      :visible.sync="confirmVisible"
      @confirm="onConfirmDelete"
      :onCancel="onCancel"
    >
    </t-dialog>
    <!-- 新建爬虫弹窗 -->
    <t-dialog header="新建爬虫" :visible.sync="formVisible" :width="680" :footer="false">
      <div slot="body">
        <!-- 表单内容 -->
        <t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
          <t-form-item label="爬虫平台" name="platform">
            <t-select v-model="formData.platform" clearable :style="{ width: '480px' }">
              <t-option v-for="(item, index) in platformOptions" :value="item.value" :label="item.label" :key="index">
                {{ item.label }}
              </t-option>
            </t-select>
          </t-form-item>
          <t-form-item label="爬虫类型" name="type">
            <t-select v-model="formData.type" clearable :style="{ width: '480px' }">
              <t-option v-for="(item, index) in typeOptions" :value="item.value" :label="item.label" :key="index">
                {{ item.label }}
              </t-option>
            </t-select>
          </t-form-item>
          <t-form-item label="关键词信息" name="keywords">
            <t-input :style="{ width: '480px' }" v-model="formData.keywords" placeholder="请输入关键词信息"></t-input>
          </t-form-item>
          <t-form-item label="cookies信息" name="cookies">
            <t-input :style="{ width: '480px' }" v-model="formData.cookies" placeholder="请输入cookies信息"></t-input>
          </t-form-item>
          <t-form-item label="爬取评论" name="comment">
            <t-switch v-model="formData.comment" />
          </t-form-item>
          <t-form-item label="爬取子评论" name="subComment">
            <t-switch v-model="formData.subComment" />
          </t-form-item>
          <t-form-item label="备注" name="remark">
            <t-textarea
              :style="{ width: '480px' }"
              v-model="formData.remark"
              placeholder="请输入描述信息"
              name="description"
            >
            </t-textarea>
          </t-form-item>
          <t-form-item style="float: right">
            <t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
            <t-button theme="primary" type="submit">确定</t-button>
          </t-form-item>
        </t-form>
      </div>
    </t-dialog>
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import { SearchIcon } from 'tdesign-icons-vue';
import { CRAWLER_STATUS } from '@/constants';
import { mapState, mapGetters } from 'vuex';

const INITIAL_DATA = {
  platform: '',
  type: '',
  keywords: '',
  cookies: '',
  comment: false,
  subComment: false,
  remark: '',
};

export default Vue.extend({
  name: 'ListBase',
  components: {
    SearchIcon,
  },
  data() {
    return {
      CRAWLER_STATUS,
      dataLoading: false,
      data: [],
      selectedRowKeys: [],
      searchValue: '',
      columns: [
        { colKey: 'row-select', type: 'multiple', width: 64, fixed: 'left' },
        {
          title: '平台名称',
          align: 'left',
          width: 100,
          ellipsis: true,
          colKey: 'platform',
          fixed: 'left',
        },
        { title: '爬虫类型', colKey: 'type', width: 100, cell: { col: 'type' } },
        {
          title: '关键词信息',
          width: 100,
          ellipsis: true,
          colKey: 'keywords',
        },
        {
          title: '创建时间',
          width: 100,
          ellipsis: true,
          colKey: 'createTime',
        },
        {
          align: 'left',
          fixed: 'right',
          width: 150,
          colKey: 'remark',
          title: '备注',
        },
        {
          align: 'left',
          fixed: 'right',
          width: 50,
          colKey: 'status',
          title: '状态',
        },
        {
          align: 'center',
          fixed: 'right',
          width: 200,
          colKey: 'op',
          title: '操作',
        },
      ],
      platformOptions: [
        { label: '小红书', value: 'xhs' },
        { label: '抖音', value: 'douyin' },
        { label: '哔哩哔哩', value: 'bilibili' },
        { label: '微博', value: 'weibo' },
        { label: '快手', value: 'kuaishou' },
        { label: '百度贴吧', value: 'tieba' },
        { label: '知乎', value: 'zhihu' },
      ],
      typeOptions: [
        { label: '关键词搜索', value: 'search' },
        { label: '帖子详情', value: 'detail' },
        { label: '创作者主页数据', value: 'creator' },
      ],
      formData: { ...INITIAL_DATA },
      rules: {
        platform: [{ required: true, message: '请选择平台名称', type: 'error' }],
        type: [{ required: true, message: '请选择爬虫类型', type: 'error' }],
        keywords: [{ required: true, message: '请输入关键词信息', type: 'error' }],
        cookies: [{ required: true, message: '请输入cookies信息', type: 'error' }],
      },
      formVisible: false,
      rowKey: 'index',
      tableLayout: 'auto',
      verticalAlign: 'top',
      hover: true,
      rowClassName: (rowKey: string) => `${rowKey}-class`,
      pagination: {
        defaultPageSize: 20,
        defaultCurrent: 1,
      },
      confirmVisible: false,
      deleteIdx: -1,
      runningCrawlers: {} as Record<number, boolean>,
    };
  },
  computed: {
    confirmBody() {
      if (this.deleteIdx > -1) {
        const { name } = this.data?.[this.deleteIdx];
        return `删除后，${name}的所有爬虫信息将被清空，且无法恢复`;
      }
      return '';
    },
    ...mapState('notification', ['msgData']),
    ...mapGetters('notification', ['unreadMsg']),
    offsetTop() {
      return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
    },
  },
  mounted() {
    this.fetchData();
  },

  methods: {
    getContainer() {
      return document.querySelector('.tdesign-starter-layout');
    },
    rehandlePageChange(curr, pageInfo) {
      console.log('分页变化', curr, pageInfo);
    },
    rehandleSelectChange(selectedRowKeys: number[]) {
      this.selectedRowKeys = selectedRowKeys;
    },
    rehandleChange(changeParams, triggerAndData) {
      console.log('统一Change', changeParams, triggerAndData);
    },
    handleClickDetail(row: Record<string, any>): void {
      this.$router.push({
        path: '/data-crawler/detail',
        query: { item: JSON.stringify(row) },
      });
    },
    handleClickDelete(row: { rowIndex: any }) {
      this.deleteIdx = row.rowIndex;
      this.confirmVisible = true;
    },
    onConfirmDelete() {
      // 真实业务请发起请求
      this.data.splice(this.deleteIdx, 1);
      this.pagination.total = this.data.length;
      const selectedIdx = this.selectedRowKeys.indexOf(this.deleteIdx);
      if (selectedIdx > -1) {
        this.selectedRowKeys.splice(selectedIdx, 1);
      }
      this.confirmVisible = false;
      this.$message.success('删除成功');
      this.resetIdx();
    },
    onCancel() {
      this.resetIdx();
    },
    resetIdx() {
      this.deleteIdx = -1;
    },

    // 新增方法：检查爬虫是否在运行
    isRunning(row: any): boolean {
      return this.runningCrawlers[row.index] || false;
    },

    // 新增方法：启动爬虫
    async startCrawler(row: any) {
      try {
        const response = await this.$request.post('/api/start-crawler', { id: row.index });
        if (response.code === 0) {
          this.$message.success('爬虫启动成功');
          // 更新按钮状态
          this.$set(this.runningCrawlers, row.index, true);
          // 修改行状态为进行中
          row.status = 1;
          // 开始轮询状态
          this.pollCrawlerStatus(row.index, row.name);
        } else {
          this.$message.error(`启动失败：${response.message}`);
          // 发送失败通知
          this.addNotification({
            id: this.generateUniqueId(),
            content: `爬虫任务【${row.name}】启动失败：${response.message}`,
            type: '爬虫通知',
            status: true,
            collected: false,
            date: this.getCurrentDate(),
            quality: 'low',
          });
        }
      } catch (error) {
        this.$message.error('启动爬虫异常');
        // 发送异常通知
        this.addNotification({
          id: this.generateUniqueId(),
          content: `爬虫任务【${row.name}】启动异常。`,
          type: '爬虫通知',
          status: true,
          collected: false,
          date: this.getCurrentDate(),
          quality: 'high',
        });
      }
    },

    // 新增方法：轮询爬虫状态
    pollCrawlerStatus(id: number, name: string) {
      const interval = setInterval(async () => {
        try {
          const response = await this.$request.get('/api/get-crawler-status', { params: { id } });
          if (response.code === 0) {
            const { status } = response.data;
            const row = this.data.find((item: any) => item.index === id);
            if (row) {
              row.status = status;
              if (status === 2 || status === 3) {
                // 停止轮询
                clearInterval(interval);
                // 更新按钮状态
                this.$delete(this.runningCrawlers, id);
                if (status === 2) {
                  this.$message.success('爬虫已完成');
                  // 发送成功通知
                  this.addNotification({
                    id: this.generateUniqueId(),
                    content: `爬虫任务【${name}】已完成。`,
                    type: '爬虫通知',
                    status: true,
                    collected: false,
                    date: this.getCurrentDate(),
                    quality: 'high',
                  });
                } else if (status === 3) {
                  this.$message.error('爬虫运行失败');
                  // 发送失败通知
                  this.addNotification({
                    id: this.generateUniqueId(),
                    content: `爬虫任务【${name}】运行失败。`,
                    type: '爬虫通知',
                    status: true,
                    collected: false,
                    date: this.getCurrentDate(),
                    quality: 'low',
                  });
                }
              }
            }
          } else {
            this.$message.error(`状态查询失败：${response.message}`);
            clearInterval(interval);
            this.$delete(this.runningCrawlers, id);
            // 发送查询失败通知
            this.addNotification({
              id: this.generateUniqueId(),
              content: `爬虫任务【${name}】状态查询失败：${response.message}`,
              type: '爬虫通知',
              status: true,
              collected: false,
              date: this.getCurrentDate(),
              quality: 'low',
            });
          }
        } catch (error) {
          this.$message.error('查询爬虫状态异常');
          clearInterval(interval);
          this.$delete(this.runningCrawlers, id);
          // 发送查询异常通知
          this.addNotification({
            id: this.generateUniqueId(),
            content: `爬虫任务【${name}】状态查询异常。`,
            type: '爬虫通知',
            status: true,
            collected: false,
            date: this.getCurrentDate(),
            quality: 'high',
          });
        }
      }, 3000); // 每3秒轮询一次
    },

    // 新增方法：添加通知到 Vuex
    addNotification(newMsg: any) {
      this.$store.commit('notification/addMsgData', newMsg);
    },

    // 新增方法：生成唯一ID
    generateUniqueId(): string {
      return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    },

    // 新增方法：获取当前日期时间
    getCurrentDate(): string {
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, '0');
      const day = String(now.getDate()).padStart(2, '0');
      const hours = String(now.getHours()).padStart(2, '0');
      const minutes = String(now.getMinutes()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}`;
    },

    // 获取数据方法保持不变
    async fetchData() {
      this.dataLoading = true;
      try {
        const response = await this.$request.get('/api/get-crawler-list');
        if (response.code === 0) {
          this.data = response.data.list;
          this.pagination.total = this.data.length;
        }
      } catch (error) {
        console.error('获取数据失败:', error);
      } finally {
        this.dataLoading = false;
      }
    },

    // 提交方法保持不变
    async onSubmit({ result, firstError }): Promise<void> {
      if (!firstError) {
        try {
          const response = await this.$request.post('/api/post', this.formData);
          if (response.code === 0) {
            this.$message.success('提交成功');
            this.formVisible = false;
            this.data.unshift(response.data.body);
            this.pagination.total = this.data.length;
          } else {
            this.$message.warning('提交失败');
          }
        } catch (error) {
          console.error('提交失败:', error);
          this.$message.error('提交异常');
        }
      } else {
        console.log('Errors: ', result);
        this.$message.warning(firstError);
      }
    },

    onClickCloseBtn() {
      this.formData = { ...INITIAL_DATA };
      this.formVisible = false;
    },
  },
});
</script>

<style lang="less" scoped>
@import '@/style/variables';

.payment-col {
  display: flex;

  .trend-container {
    display: flex;
    align-items: center;
    margin-left: 8px;
  }
}

.left-operation-container {
  padding: 0 0 6px 0;
  margin-bottom: 16px;

  .selected-count {
    display: inline-block;
    margin-left: var(--td-comp-margin-s);
    color: var(--td-text-color-secondary);
  }
}

.search-input {
  width: 260px;
}

.t-button + .t-button {
  margin-left: var(--td-comp-margin-s);
}

.running-button {
  color: blue;
}
</style>
